﻿using System;
using System.Windows.Input;
using XEvolve.Core;
using XEvolve.Core.Runtime;
using XEvolve.Core.Runtime.Attributes;
using XEvolve.Presentation.Input;
using XEvolve.Presentation.Input.Internal;
using XEvolve.Presentation.Internal;
using System.Windows;

namespace XEvolve.Presentation
{
    [PluginId("xevolve.presentation")]
    public class PresentationPlugin : Plugin
    {
        public PresentationPlugin([Required("xevolve.core")]Plugin[] dependencies) : base(dependencies)
        {
        }

        protected override void Initialize(Platform platform)
        {
            RegisterExtensionPoints(platform);            
            RegisterServices(platform);
            RegisterPreDefinedCommandHandlers(platform);
            RegisterObjectModelExtensions(platform);
        }

        private static void RegisterObjectModelExtensions(Platform platform)
        {
            platform.Registry.RegisterAdapterFactory<WindowsInputICommandSourceAdapterFactory>();
            platform.Registry.RegisterAdapterFactory<XEvolveCommandSourceAdapterFactory>();            
        }

        private static void RegisterServices(Platform platform)
        {
            platform.RegisterService<XCommandManager, XCommandManager>();
            platform.RegisterService<AdvisorManager, AdvisorManager>();
            platform.RegisterService<INavigator, ViewManager>();
            platform.RegisterService<IThemeManager, ThemeManager>();
            platform.RegisterService(typeof(MarkupManager), new MarkupManager(platform));
        }

        private static void RegisterExtensionPoints(Platform platform)
        {
            platform.Registry.RegisterExtensionPoint("xevolve.views", false);
            platform.Registry.RegisterExtensionPoint("xevolve.presentation.advisors", false);
            platform.Registry.RegisterExtensionPoint("xevolve.presentation.advisor.bindings");            
            platform.Registry.RegisterExtensionPoint("xevolve.presentation.command.bindings");
            platform.Registry.RegisterExtensionPoint("xevolve.presentation.command.handlers");
            platform.Registry.RegisterExtensionPoint("xevolve.themes");
            platform.Registry.RegisterExtensionPoint("xevolve.themes.colorSchema");
        }

        private static void RegisterPreDefinedCommandHandlers(Platform platform)
        {
            platform.Registry.RegisterHandler<NavigationHandler>();
            platform.Registry.RegisterCommandBinding("XEvolve.Window", Navigation.NavigateTo, typeof(NavigationHandler));
        }
    }

    public static class PresentationExtensionPoints
    {
        public static void RegisterView<ViewType>(this IExtensionRegistry registry, object viewId) where ViewType : Window
        {
            registry.RegisterExtension("xevolve.views", viewId, typeof(ViewType));
        }

        public static void RegisterHandler<HandlerType>(this IExtensionRegistry registry) where HandlerType : ICommandHandler
        {
            registry.RegisterExtension("xevolve.presentation.command.handlers", typeof(HandlerType), typeof(HandlerType));
        }

        public static void RegisterCommandBinding(this IExtensionRegistry registry, string context, ICommand command, Type handlerType)
        {
            registry.RegisterExtension("xevolve.presentation.command.bindings", new XCommandBinding(context, command, handlerType));
        }

        public static void RegisterAdvisor<AdvisorType>(this IExtensionRegistry registry) where AdvisorType : IDependencyObjectAdvisor
        {
            registry.RegisterExtension("xevolve.presentation.advisors", typeof(AdvisorType), typeof(AdvisorType));
        }

        public static void RegisterAdvisorBinding(this IExtensionRegistry registry, string elementId, Type advisorType)
        {
            registry.RegisterExtension("xevolve.presentation.advisor.bindings", new AdvisorBinding(elementId, advisorType));
        }

        public static void RegisterTheme(this IExtensionRegistry registry, string name, string uriString)
        {
            var component = Application.LoadComponent(new Uri(uriString, UriKind.RelativeOrAbsolute));
            registry.RegisterExtension("xevolve.themes", name, component);
        }

        public static void RegisterThemeColorSchema(this IExtensionRegistry registry, string name, string uriString, params string[] applicableThemes)
        {
            registry.RegisterExtension("xevolve.themes.colorSchema", new ColorSchema(name, applicableThemes, (ResourceDictionary)Application.LoadComponent(new Uri(uriString, UriKind.RelativeOrAbsolute))));
        }
    }
}
